home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Info-Mac 4
/
Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso
/
Development
/
General
/
CW TCL port package
/
Template Munger
/
Source
/
MakeTemplate.c
< prev
next >
Wrap
Text File
|
1994-05-30
|
10KB
|
390 lines
/*
** MakeTemplate.c
*/
short def_vRef = 0; // folder for definition (input) files
long def_parID = 0;
short def_fRef = 0; // file reference for current definition file
Handle defText; // handle for definition file
short out_vRef = 0; // folder for output files
long out_parID = 0;
short out_fRef = 0; // file reference for current output file
Handle outText; // handle for new output file
extern Str63 outFileName; // name of template macro file name (typically ___.tm.h)
extern Str63 defnFileName; // name of template definition file name (typically ___.tem)
extern char ch_type [256];
Str255 junkBfr; // junk characters buffer
Boolean hadToken; // true if a token occurred on this line
Boolean inTemplateDefn; // true if defining (rather than declaring) template
char outClass[255]; // class of template we're building
char wildcard[255]; // class of wildcard we're defining (macro argument)
short tokenState; // state of token parser
// 0 = normal operation
// 1 = encountered 'template', expecting '<'
// 2 = encountered 'template <', expecting 'class'
// 3 = encountered 'template <class', expecting (type)
// 4 = encountered 'template <class (type)', expecting '>'
// 5 = encountered 'template <class (type)>', expecting 'class' or function type
// 6 = encountered 'template <class (type)> class', expecting (class)
// then cycles back to 0
// 10 = encountered '<', check for type
// 11 = encountered '< (type)', expecting '>'
// 20 = encountered (class), name of base class, expecting '(' – constructor/destructor
void OutCStr(char* str);
void OutPStr(unsigned char* str);
extern void ErrMsg ( unsigned char * why , unsigned char * file , short code );
Boolean OpenOutfile()
{
OSErr err;
err = HCreate(out_vRef, out_parID, outFileName, 'MPCC', 'TEXT');
if (err == -48) { // duplicate file name, delete old file (dangerous... I know!)
err = HDelete(out_vRef, out_parID, outFileName);
if (!err) {
err = HCreate(out_vRef, out_parID, outFileName, 'MPCC', 'TEXT');
}
}
if (err) {
ErrMsg("\pCreating", outFileName, err);
return true;
}
err = HOpenDF ( out_vRef , out_parID , outFileName , fsRdWrPerm , & out_fRef ) ;
if ( err ) {
ErrMsg ( "\pOpening" , outFileName , err ) ;
return true;
}
outText = NewHandle (0) ;
if ( ! outText ) {
ErrMsg ( "\pAllocating" , outFileName , MemError ( ) ) ;
FSClose ( out_fRef ) ;
return true;
}
OutCStr("// ");
OutPStr(outFileName);
OutCStr("\r//\r// Macro template file\r// Generated by Template Munger\r\r");
junkBfr[0] = 0;
outClass[0] = 0;
wildcard[0] = 0;
hadToken = false;
inTemplateDefn = false;
return false;
}
void CloseOutfile()
{
OSErr err;
long size ;
size = GetHandleSize ( outText ) ;
err = SetEOF ( out_fRef , size ) ;
if ( ! err ) {
err = SetFPos ( out_fRef , fsFromStart , 0L ) ;
}
if ( err ) {
ErrMsg ( "\pFinishing" , outFileName , err ) ;
FSClose ( out_fRef ) ;
DisposeHandle ( outText ) ;
return ;
}
HLock ( outText ) ;
err = FSWrite ( out_fRef , & size , * outText ) ;
if ( err ) {
ErrMsg ( "\pWriting" , outFileName , err ) ;
FSClose ( out_fRef ) ;
DisposeHandle ( outText ) ;
return ;
}
err = FSClose ( out_fRef ) ;
if ( ! err ) {
err = FlushVol ( NULL , out_vRef ) ;
}
DisposeHandle ( outText ) ;
if ( err ) {
ErrMsg ( "\pClosing" , outFileName , err ) ;
}
}
void OutCStr(char* str)
{
long len = 0;
char* p = str;
while (*p++)
len++;
PtrAndHand(str, outText, len);
}
void OutPStr(unsigned char* str)
{
long len = *str;
PtrAndHand(str+1, outText, len);
}
void OutJunkChar(char theChar)
{
if ((tokenState == 10) && ((theChar != ' ') && (theChar != '\t'))) {
junkBfr[++junkBfr[0]] = '<'; // make sure that <> or <= doesn't trigger template expansion
tokenState = 0;
}
junkBfr[++junkBfr[0]] = theChar;
if (junkBfr[0] > 200) {
OutPStr(junkBfr);
junkBfr[0] = 0;
}
}
Boolean OutToken(char* theToken)
{
Boolean tokValid = true; // set to false if invalid token for context
if ((junkBfr[0]) && (tokenState == 0)) {
OutPStr(junkBfr);
junkBfr[0] = 0;
}
hadToken = true;
switch (tokenState) {
case 0: // normal operation: check for keywords
if (!strcmp(theToken, "template")) {
tokenState = 1; // found a template declaration, parse it
break;
}
if (!strcmp(theToken, "<")) {
tokenState = 10; // might be a reference to the template, parse it
if (junkBfr[0]) { // get other characters out in proper sequence
OutPStr(junkBfr);
junkBfr[0] = 0;
}
break;
}
if (!strcmp(theToken, outClass)) { // template class name, see if it's constructor/destructor
tokenState = 20;
break;
}
OutCStr(theToken); // neither of the above, just copy it
break;
case 1: // got 'template', expect '<'
if (strcmp(theToken, "<")) {
tokValid = false;
tokenState = 0;
OutCStr("template"); // just copy the invalid stuff to file
OutToken(theToken);
break;
}
tokenState++; // valid input, continue chain
break;
case 2: // got 'template <', expect 'class'
if (strcmp(theToken, "class")) {
tokValid = false;
tokenState = 0;
OutCStr("template <"); // just copy the invalid stuff to file
OutToken(theToken);
break;
}
tokenState++; // valid input, continue chain
break;
case 3: // got 'template <class', expect (type)
if (ch_type[theToken[0]] != 4) { // first character must be alpha
tokValid = false;
tokenState = 0;
OutCStr("template <class "); // just copy the invalid stuff to file
OutToken(theToken);
break;
}
strcpy(wildcard, theToken); // keep this thing around
tokenState++; // valid input, continue chain
break;
case 4: // got 'template <class (type)', expect '>'
if (strcmp(theToken, ">")) {
tokValid = false;
tokenState = 0;
OutCStr("template <class "); // just copy the invalid stuff to file
OutCStr(wildcard);
OutToken(theToken);
break;
}
tokenState++; // valid input, continue chain
break;
case 5: // got 'template <class (type)>', expect 'class' or function type
if (inTemplateDefn) {
tokenState = 0; // just dump the 'template <class (type)>' line
junkBfr[0] = 0;
OutToken(theToken);
break;
} else {
if (strcmp(theToken, "class")) { // declaring class, expect 'class' only
tokValid = false;
tokenState = 0;
OutCStr("template <class "); // just copy the invalid stuff to file
OutCStr(wildcard);
OutCStr(">");
OutToken(theToken);
break;
}
tokenState++; // valid input, continue chain
break;
}
case 6: // got 'template <class (type)> class', expect '(type)'
if (ch_type[theToken[0]] != 4) { // first character must be alpha
tokValid = false;
tokenState = 0;
OutCStr("template <class "); // just copy the invalid stuff to file
OutCStr(wildcard);
OutToken(theToken);
break;
}
strcpy(outClass, theToken); // keep this thing around
OutCStr("\r#define TM_DECLARE_"); // valid input, write macro header
OutCStr(outClass);
OutCStr("(");
OutCStr(wildcard);
OutCStr(") \\\rclass ");
OutCStr(outClass);
OutCStr("_ ## ");
OutCStr(wildcard);
junkBfr[0] = 0; // clear junk buffer
tokenState = 0; // resume normal operation
break;
case 10: // got '<', might get (wildcard type)
if (strcmp(theToken, wildcard)) {
tokenState = 0; // nope… just treat it like anything else
OutCStr("<"); // make sure the '<' charater gets out properly
OutToken(theToken); // and print this other token
break;
}
tokenState++; // valid input, continue chain
break;
case 11: // got '< (wildcard)', expecting '>'
if (strcmp(theToken, ">")) {
tokValid = false;
tokenState = 0;
OutCStr("<"); // just copy the invalid stuff to file
OutCStr(wildcard);
OutToken(theToken);
break;
}
OutCStr("_ ## "); // was valid, substitute template expansion
OutCStr(wildcard);
junkBfr[0] = 0;
tokenState = 0; // back to normal
break;
case 20: // got class name, look for '('
if (!strcmp(theToken, "(")) {
OutCStr(outClass); // found '(', substitute expanded constructor/destructor name
OutCStr("_ ## ");
OutCStr(wildcard);
}
else
OutCStr(outClass); // no '(' found, just print it as is
tokenState = 0; // print the stuff
OutToken(theToken);
break;
default: // something broke!
Message("\rInternal error");
tokenState = 0;
OutToken(theToken);
break;
}
hadToken = true;
return tokValid; // token was valid…
}
void OutNewLine()
{
short i;
char* p;
if (tokenState != 0) {
OutJunkChar(' '); // ignore new lines in the midst of template declarations
return;
}
i = junkBfr[0]+1;
p = (char*) &junkBfr[i]; // strip all trailing spaces from "junk buffer"
while (--p, --i) {
if ((*p != ' ') && (*p != '\t'))
break; // non-blank, must print it
else
junkBfr[0]--; // remove this character
}
if ((!hadToken) && (!junkBfr[0])) // completely blank line, skip it
return;
if (junkBfr[0]) {
OutPStr(junkBfr);
junkBfr[0] = 0;
}
hadToken = false;
OutCStr(" \\\r"); // be sure to continue macro definition
}
void EndTemplateDeclaration()
{
if (junkBfr[0]) {
OutPStr(junkBfr);
junkBfr[0] = 0;
}
OutCStr("};\r");
}
void StartTemplateDefn()
{
if (junkBfr[0]) {
OutPStr(junkBfr);
junkBfr[0] = 0;
}
OutCStr("\r\r\r#define TM_DEFINE_"); // write macro header – using same class name
OutCStr(outClass);
OutCStr("(");
OutCStr(wildcard);
OutCStr(") \\\r");
junkBfr[0] = 0; // clear junk buffer
tokenState = 0; // resume normal operation
inTemplateDefn = true; // …except we want to allow template function definitions
}
void EndTemplateDefn()
{
if (junkBfr[0]) {
OutPStr(junkBfr);
junkBfr[0] = 0;
}
OutCStr("\r\r");
}